package org.lep.leetcode.datastructure.linkedlist.linkedlistcycle;

/**
 * Source : https://oj.leetcode.com/problems/linked-list-cycle/
 *
 * Created by lverpeng on 2017/9/14.
 *
 * Given a linked list, determine if it has a cycle in it.
 *
 * Follow up:
 * Can you solve it without using extra space?
 */
public class LinkedListCycle {

    /**
     * 判断一个链表是否有循环
     *
     * 遍历链表，将所有遍历过的ndeo放入hash表，如果当前节点已经在hash表中，说明有循环，直到遍历结束。
     *
     * 上线的方法需要额外的空间，使用双指针法：
     * slow指针每次移动一个node，fast每次移动两个node，在遍历结束前，如果slow == fast，那么该链表是循环的
     *
     *
     * @param head
     * @return
     */
    public boolean hasCycle (LinkedNode head) {
        if (head == null) {
            return false;
        }
        LinkedNode slow = head;
        LinkedNode fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

    private class LinkedNode {
        int value;
        LinkedNode next;

    }

    /**
     * 创建普通的链表
     * @param arr
     * @return
     */
    public LinkedNode createList (int[] arr) {
        if (arr.length == 0) {
            return null;
        }
        LinkedNode head = new LinkedNode();
        head.value = arr[0];
        LinkedNode pointer = head;
        for (int i = 1; i < arr.length; i++) {
            LinkedNode node = new LinkedNode();
            node.value = arr[i];
            pointer.next = node;
            pointer = pointer.next;
        }
        return head;
    }

    /**
     * 将链表变为循环链表，循环起始为第index个node
     * @param head
     * @param index
     */
    public void makeCycle (LinkedNode head, int index) {
        if (head == null) {
            return;
        }
        LinkedNode tail = head;
        int count = 1;
        while (tail.next != null) {
            tail = tail.next;
            count++;
        }
        LinkedNode p = head;
        if (index > count) {
            index = index % count;
        } else if (index < 0) {
            index = Math.abs(index);
        }
        while (p != null) {
            index--;
            if (index < 1) {
                tail.next = p;
                break;
            }
            p = p.next;
        }

    }

    public static void main(String[] args) {
        LinkedListCycle linkedListCycle = new LinkedListCycle();
        LinkedNode list = linkedListCycle.createList(new int[]{1,2,3,4,5});

        System.out.println(linkedListCycle.hasCycle(list) + " == false");

        linkedListCycle.makeCycle(list, 2);
        System.out.println(linkedListCycle.hasCycle(list) + " == true");
    }
}
